home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / stdio / c / scan < prev    next >
Text File  |  1996-11-09  |  14KB  |  871 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/stdio/c/RCS/scan,v $
  4.  * $Date: 1996/04/19 21:32:42 $
  5.  * $Revision: 1.1 $
  6.  * $State: Rel $
  7.  * $Author: simon $
  8.  *
  9.  * $Log: scan,v $
  10.  * Revision 1.1  1996/04/19 21:32:42  simon
  11.  * Initial revision
  12.  *
  13.  ***************************************************************************/
  14.  
  15. static const char rcs_id[] = "$Id: scan,v 1.1 1996/04/19 21:32:42 simon Rel $";
  16.  
  17. /* Implements __scanf(fp,format,argp,cnt) which is called by all
  18.  * scanf() functions to perform formatted input. __scanf() returns a count
  19.  * of the number of characters read. *cnt is assigned to an item count. */
  20.  
  21. /* A conversion is of the form "%[*][width][size]function".
  22.  * For full details RTFM for scanf(3). */
  23.  
  24. #include <sys/syslib.h>
  25.  
  26. #include <stddef.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include <stdarg.h>
  31. #include <stdio.h>
  32.  
  33. #define IGNORE(x) x = x
  34.  
  35. __STDIOLIB__
  36.  
  37. #define ungetc(c,f) \
  38.     (((f)->i_ptr > (f)->i_base) ? ((f)->i_cnt++,*--(f)->i_ptr = (c)) : -1)
  39.  
  40. /* To avoid truncation SCBUFSIZ should be 256+.
  41.  * This library will *not* buffer overflow unless SCBUFSIZ < 4. */
  42.  
  43. #define SCBUFSIZ    256    /* size of buffer for %feEgG & %[ */
  44.  
  45.  
  46. /* the prototypes for the input functions */
  47.  
  48. static int __s_nin (FILE *, va_list *, const char **);
  49.  
  50. static int __s_char (FILE *, va_list *, const char **);
  51. static int __s_str (FILE *, va_list *, const char **);
  52. static int __s_sdec (FILE *, va_list *, const char **);
  53. static int __s_sint (FILE *, va_list *, const char **);
  54. static int __s_uoct (FILE *, va_list *, const char **);
  55. static int __s_udec (FILE *, va_list *, const char **);
  56. static int __s_uhex (FILE *, va_list *, const char **);
  57. static int __s_fdbl (FILE *, va_list *, const char **);
  58. static int __s_ptr (FILE *, va_list *, const char **);
  59. static int __s_sdel (FILE *, va_list *, const char **);
  60.  
  61.  
  62. /* __scnt is set to the number of characters read by __scanf() and
  63.  * is used by __s_nin() to output the number of characters read. */
  64.  
  65. static size_t __scnt;
  66.  
  67. static int __scflag;        /* assignment suppression flag */
  68. static int __scsize;        /* -1 = unspecified */
  69. static unsigned int __scwidth;    /* width */
  70.  
  71. static signed char __scfnc[32] =    /* conversions */
  72. {
  73.   -1, -1,
  74.   1,                /* %c */
  75.   3,                /* %d */
  76.   8,                /* %eE */
  77.   8,                /* %f */
  78.   8,                /* %gG */
  79.   -1,
  80.   4,                /* %i */
  81.   -1, -1, -1, -1,
  82.   0,                /* %n */
  83.   5,                /* %o */
  84.   9,                /* %p */
  85.   -1, -1,
  86.   2,                /* %s */
  87.   -1,
  88.   6,                /* %u */
  89.   -1, -1,
  90.   7,                /* %xX */
  91.   -1, -1, -1, -1, -1, -1, -1, -1
  92. };
  93.  
  94. /* __scfn[] is the array of input functions called by __scanf() -
  95.  * They return a value indicating whether they successfully interpreted
  96.  * the input or not. 0 indicates failure; a +ve value is a count
  97.  * of the number of characters read. */
  98.  
  99. static int (*__scfn[]) (FILE *, va_list *, const char **) =
  100. {
  101.   __s_nin,            /* %n no. of characters read so far */
  102.     __s_char,            /* %c character */
  103.     __s_str,            /* %s string */
  104.     __s_sdec,            /* %d signed decimal */
  105.     __s_sint,            /* %i signed integer */
  106.     __s_uoct,            /* %o unsigned octal */
  107.     __s_udec,            /* %u unsigned decimal */
  108.     __s_uhex,            /* %xX unsigned hex */
  109.     __s_fdbl,            /* %feEgG float (double) */
  110.     __s_ptr,            /* %p unsigned hex value of pointer */
  111.     __s_sdel            /* %[ delimited string */
  112. };
  113.  
  114.  
  115. /* __scanf() */
  116.  
  117. int
  118. __scanf (register FILE * f, const char *format, va_list ap, int *cnt)
  119. {
  120.   register const char *s1 = format;
  121.   register int n = 0;
  122.   register int c;
  123.  
  124.   for (;;)
  125.     {
  126.       if (!(c = *s1++))
  127.     goto ret;
  128.  
  129.       if (isspace (c))
  130.     continue;        /* white space in formatting string is ignored */
  131.  
  132.       if (c != '%')
  133.     {
  134.       register int m, l = 0;
  135.  
  136.     match:
  137.       do
  138.         {
  139.           if ((l++, m = getc (f)) < 0)
  140.         {
  141.           if (!n)
  142.             goto eof;
  143.           goto ret;
  144.         }
  145.         }
  146.       while (isspace (m));
  147.       __scnt += l;
  148.       if (m == c)
  149.         continue;
  150.       (void) ungetc (m, f);
  151.       goto ret;
  152.     }
  153.       else
  154.     {
  155.       if (!(c = *s1++))
  156.         goto ret;
  157.       if (c == '%')
  158.         goto match;
  159.     }
  160.  
  161.       {                /* we now have a % conversion */
  162.     register int i, j;
  163.     const char *s;
  164.  
  165. /* looking for "%[*][width][size]function" */
  166.  
  167. /* set __scflag */
  168.  
  169.     __scflag = 0;
  170.     if (c == '*')
  171.       {
  172.         if (!(c = *s1++))
  173.           goto ret;
  174.         __scflag = 1;
  175.       }
  176.  
  177. /* set __scwidth */
  178.  
  179.     __scwidth = 0;
  180.     if (isdigit (c))
  181.       {
  182.         __scwidth = (unsigned int) strtoul (s1 - 1, (char **) &s, 0);
  183.         s1 = s;
  184.         if (!(c = *s1++))
  185.           goto ret;
  186.         if (__scwidth > SCBUFSIZ)
  187.           __scwidth = SCBUFSIZ;
  188.       }
  189.  
  190. /* set __scsize */
  191.  
  192.     switch (c)
  193.       {
  194.       case 'h':
  195.         __scsize = 0;
  196.         if (!(c = *s1++))
  197.           goto ret;
  198.         break;
  199.       case 'l':
  200.         __scsize = 1;
  201.         if (!(c = *s1++))
  202.           goto ret;
  203.         break;
  204.       case 'L':
  205.         __scsize = 2;
  206.         if (!(c = *s1++))
  207.           goto ret;
  208.         break;
  209.       default:
  210.         __scsize = -1;
  211.         break;
  212.       }
  213.  
  214. /* call appropriate input function */
  215.  
  216.     i = (c == '[') ? 10 : __scfnc[(_tolower (c) - 'a') & 31];
  217.  
  218.     if (i >= 0)
  219.       {
  220.         s = s1;
  221.         j = __funcall ((*__scfn[i]), (f, (va_list *) (&ap), &s));
  222.         s1 = s;
  223.  
  224.         if (j < 0 && !n)
  225.           goto eof;
  226.         else if (j <= 0)
  227.           goto ret;
  228.         else
  229.           {
  230.         __scnt += j;
  231.         if (!__scflag)
  232.           n++;
  233.           }
  234.       }
  235.     else
  236.       {
  237.         if (!n)
  238.           goto eof;
  239.         goto ret;
  240.       }
  241.       }
  242.     }
  243.  
  244. ret:*cnt = n;
  245.   return (__scnt);
  246.  
  247. eof:*cnt = 0;
  248.   return (-1);
  249. }
  250.  
  251.  
  252. /* __s_nin() */
  253.  
  254. static int
  255. __s_nin (register FILE * f, va_list * ap, const char **e)
  256. {
  257.   IGNORE (e);
  258.   IGNORE (f);
  259.   if (!__scflag)
  260.     {
  261.       switch (__scsize)
  262.     {
  263.     case 0:
  264.       *va_arg (*ap, short *) = (short) __scnt;
  265.       break;
  266.     case 1:
  267.       *va_arg (*ap, long *) = (long) __scnt;
  268.       break;
  269.     default:
  270.       *va_arg (*ap, int *) = (int) __scnt;
  271.       break;
  272.     }
  273.     }
  274.  
  275.   return (0);
  276. }
  277.  
  278. /* __s_char() */
  279.  
  280. static int
  281. __s_char (register FILE * f, va_list * ap, const char **e)
  282. {
  283.   register unsigned int w;
  284.   register int n = 0;
  285.   register char *s;
  286.   register int c;
  287.  
  288.   IGNORE (e);
  289.  
  290.   w = __scwidth;
  291.   if (!w)
  292.     w = 1;            /* default - 1 char */
  293.  
  294.   s = __scflag ? 0 : va_arg (*ap, char *);
  295.  
  296.   while (w)
  297.     {
  298.       if ((c = getc (f)) < 0)
  299.     return (n ? n : -1);
  300.       if (s)
  301.     *s++ = c;
  302.       n++, w--;
  303.     }
  304.  
  305.   return (n);
  306. }
  307.  
  308. /* __s_str() */
  309.  
  310. static int
  311. __s_str (register FILE * f, va_list * ap, const char **e)
  312. {
  313.   register unsigned int w;
  314.   register int n = 0;
  315.   register char *s;
  316.   register int c;
  317.  
  318.   IGNORE (e);
  319.  
  320.   w = __scwidth;
  321.   if (!w)
  322.     w = SCBUFSIZ;
  323.  
  324.   s = __scflag ? 0 : va_arg (*ap, char *);
  325.  
  326.   do
  327.     {
  328.       if ((c = getc (f)) < 0)
  329.     {
  330.       if (s)
  331.         *s = 0;
  332.       return (-1);
  333.     }
  334.     }
  335.   while (isspace (c));
  336.  
  337.   while (!isspace (c) && w)
  338.     {
  339.       if (s)
  340.     *s++ = c;
  341.       n++, w--;
  342.       if ((c = getc (f)) < 0)
  343.     {
  344.       if (s)
  345.         *s = 0;
  346.       return (n);
  347.     }
  348.     }
  349.  
  350.   if (s)
  351.     *s = 0;
  352.   (void) ungetc (c, f);
  353.  
  354.   return (n);
  355. }
  356.  
  357. /* __s_sdec() */
  358.  
  359. static int
  360. __s_sdec (register FILE * f, va_list * ap, const char **e)
  361. {
  362.   register unsigned int w;
  363.   register int n = 0;
  364.   register int c;
  365.   register int i = 0, i_ = 0;
  366.  
  367.   IGNORE (e);
  368.  
  369.   w = __scwidth;
  370.   if (!w)
  371.     w = SCBUFSIZ;
  372.  
  373.   do
  374.     {
  375.       if ((c = getc (f)) < 0)
  376.     return (-1);
  377.     }
  378.   while (isspace (c));
  379.  
  380.   if (c == '+' || c == '-')
  381.     {
  382.       if (c == '-')
  383.     i_ = 1;
  384.       n++, w--;
  385.       if ((c = getc (f)) < 0)
  386.     goto ret;
  387.     }
  388.  
  389.   while (isdigit (c) && w)
  390.     {
  391.       i = i * 10 + (c - '0');
  392.       n++, w--;
  393.       if ((c = getc (f)) < 0)
  394.     goto ret;
  395.     }
  396.  
  397.   (void) ungetc (c, f);
  398.  
  399. ret:if (!__scflag && n)
  400.     {
  401.       if (i_)
  402.     i = -i;
  403.       switch (__scsize)
  404.     {
  405.     case 0:
  406.       *va_arg (*ap, short *) = (short) i;
  407.       break;
  408.     case 1:
  409.       *va_arg (*ap, long *) = (long) i;
  410.       break;
  411.     default:
  412.       *va_arg (*ap, int *) = i;
  413.       break;
  414.     }
  415.     }
  416.  
  417.   return (n);
  418. }
  419.  
  420. /* __s_sint() */
  421.  
  422. static int
  423. __s_sint (register FILE * f, va_list * ap, const char **e)
  424. {
  425.   register unsigned int w;
  426.   register int n = 0;
  427.   register int c;
  428.   register int i = 0, i_ = 0;
  429.   register int b = 10;
  430.  
  431.   IGNORE (e);
  432.  
  433.   w = __scwidth;
  434.   if (!w)
  435.     w = SCBUFSIZ;
  436.  
  437.   do
  438.     {
  439.       if ((c = getc (f)) < 0)
  440.     return (-1);
  441.     }
  442.   while (isspace (c));
  443.  
  444.   if (c == '+' || c == '-')
  445.     {
  446.       if (c == '-')
  447.     i_ = 1;
  448.       n++, w--;
  449.       if ((c = getc (f)) < 0)
  450.     goto ret;
  451.     }
  452.  
  453.   if (c == '0' && w)
  454.     {
  455.       b = 010;
  456.       n++, w--;
  457.       if ((c = getc (f)) < 0)
  458.     goto ret;
  459.       if ((c == 'x' || c == 'X') && w)
  460.     {
  461.       b = 0x10;
  462.       n++, w--;
  463.       if ((c = getc (f)) < 0)
  464.         goto ret;
  465.     }
  466.     }
  467.  
  468.   switch (b)
  469.     {
  470.     case 010:
  471.       while (c >= '0' && c < '8' && w)
  472.     {
  473.       i = i * b + (c - '0');
  474.       n++, w--;
  475.       if ((c = getc (f)) < 0)
  476.         goto ret;
  477.     }
  478.       break;
  479.     case 10:
  480.       while (isdigit (c) && w)
  481.     {
  482.       i = i * b + (c - '0');
  483.       n++, w--;
  484.       if ((c = getc (f)) < 0)
  485.         goto ret;
  486.     }
  487.       break;
  488.     case 0x10:
  489.       while (isxdigit (c) && w)
  490.     {
  491.       i = i * b + ((c > '9') ? ((c & 31) + 9) : (c - '0'));
  492.       n++, w--;
  493.       if ((c = getc (f)) < 0)
  494.         goto ret;
  495.     }
  496.       break;
  497.     }
  498.  
  499.   (void) ungetc (c, f);
  500.  
  501. ret:if (!__scflag && n)
  502.     {
  503.       if (i_)
  504.     i = -i;
  505.       switch (__scsize)
  506.     {
  507.     case 0:
  508.       *va_arg (*ap, short *) = (short) i;
  509.       break;
  510.     case 1:
  511.       *va_arg (*ap, long *) = (long) i;
  512.       break;
  513.     default:
  514.       *va_arg (*ap, int *) = i;
  515.       break;
  516.     }
  517.     }
  518.  
  519.   return (n);
  520. }
  521.  
  522. /* __s_uoct() */
  523.  
  524. static int
  525. __s_uoct (register FILE * f, va_list * ap, const char **e)
  526. {
  527.   register unsigned int w;
  528.   register int n = 0;
  529.   register int c;
  530.   register unsigned int i = 0;
  531.  
  532.   IGNORE (e);
  533.  
  534.   w = __scwidth;
  535.   if (!w)
  536.     w = SCBUFSIZ;
  537.  
  538.   do
  539.     {
  540.       if ((c = getc (f)) < 0)
  541.     return (-1);
  542.     }
  543.   while (isspace (c));
  544.  
  545.   while (c >= '0' && c <= '7' && w)
  546.     {
  547.       i = i * 010 + (c - '0');
  548.       n++, w--;
  549.       if ((c = getc (f)) < 0)
  550.     goto ret;
  551.     }
  552.  
  553.   (void) ungetc (c, f);
  554.  
  555. ret:if (!__scflag && n)
  556.     {
  557.       switch (__scsize)
  558.     {
  559.     case 0:
  560.       *va_arg (*ap, short *) = (short) i;
  561.       break;
  562.     case 1:
  563.       *va_arg (*ap, long *) = (long) i;
  564.       break;
  565.     default:
  566.       *va_arg (*ap, int *) = i;
  567.       break;
  568.     }
  569.     }
  570.  
  571.   return (n);
  572. }
  573.  
  574. /* __s_udec() */
  575.  
  576. static int
  577. __s_udec (register FILE * f, va_list * ap, const char **e)
  578. {
  579.   register unsigned int w;
  580.   register int n = 0;
  581.   register int c;
  582.   register unsigned int i = 0;
  583.  
  584.   IGNORE (e);
  585.  
  586.   w = __scwidth;
  587.   if (!w)
  588.     w = SCBUFSIZ;
  589.  
  590.   do
  591.     {
  592.       if ((c = getc (f)) < 0)
  593.     return (-1);
  594.     }
  595.   while (isspace (c));
  596.  
  597.   while (isdigit (c) && w)
  598.     {
  599.       i = i * 10 + (c - '0');
  600.       n++, w--;
  601.       if ((c = getc (f)) < 0)
  602.     goto ret;
  603.     }
  604.  
  605.   (void) ungetc (c, f);
  606.  
  607. ret:if (!__scflag && n)
  608.     {
  609.       switch (__scsize)
  610.     {
  611.     case 0:
  612.       *va_arg (*ap, short *) = (short) i;
  613.       break;
  614.     case 1:
  615.       *va_arg (*ap, long *) = (long) i;
  616.       break;
  617.     default:
  618.       *va_arg (*ap, int *) = i;
  619.       break;
  620.     }
  621.     }
  622.  
  623.   return (n);
  624. }
  625.  
  626. /* __s_uhex() */
  627.  
  628. static int
  629. __s_uhex (register FILE * f, va_list * ap, const char **e)
  630. {
  631.   register unsigned int w;
  632.   register int n = 0;
  633.   register int c;
  634.   register unsigned int i = 0;
  635.  
  636.   IGNORE (e);
  637.  
  638.   w = __scwidth;
  639.   if (!w)
  640.     w = SCBUFSIZ;
  641.  
  642.   do
  643.     {
  644.       if ((c = getc (f)) < 0)
  645.     return (-1);
  646.     }
  647.   while (isspace (c));
  648.  
  649.   if (c == '0' && w)
  650.     {
  651.       n++, w--;
  652.       if ((c = getc (f)) < 0)
  653.     goto ret;
  654.       if ((c == 'x' || c == 'X') && w)
  655.     {
  656.       n++, w--;
  657.       if ((c = getc (f)) < 0)
  658.         goto ret;
  659.     }
  660.     }
  661.  
  662.   while (isxdigit (c) && w)
  663.     {
  664.       i = i * 0x10 + (isdigit (c) ? (c - '0') : ((c & 7) + 9));
  665.       n++, w--;
  666.       if ((c = getc (f)) < 0)
  667.     goto ret;
  668.     }
  669.  
  670.   (void) ungetc (c, f);
  671.  
  672. ret:if (!__scflag && n)
  673.     {
  674.       switch (__scsize)
  675.     {
  676.     case 0:
  677.       *va_arg (*ap, short *) = (short) i;
  678.       break;
  679.     case 1:
  680.       *va_arg (*ap, long *) = (long) i;
  681.       break;
  682.     default:
  683.       *va_arg (*ap, int *) = i;
  684.       break;
  685.     }
  686.     }
  687.  
  688.   return (n);
  689. }
  690.  
  691. /* __s_fdbl() */
  692.  
  693. static int
  694. __s_fdbl (register FILE * f, va_list * ap, const char **e)
  695. {
  696.   register unsigned int w;
  697.   register int n = 0;
  698.   register int c;
  699.   register double i;
  700.   register char *s;
  701.   register int l = 0;
  702.  
  703. #define F_SIGN    0001
  704. #define F_DP    0002
  705. #define F_XP    0004
  706. #define F_XSIGN 0010
  707.  
  708.   IGNORE (e);
  709.  
  710.   if (!__scflag)
  711.     {
  712.       if (!(s = __sbuf))
  713.     if (!(s = __sbuf = malloc (SCBUFSIZ)))
  714.       return (0);
  715.     }
  716.   else
  717.     s = 0;
  718.  
  719.   w = __scwidth;
  720.   if (!w)
  721.     w = SCBUFSIZ;
  722.  
  723.   do
  724.     {
  725.       if ((c = getc (f)) < 0)
  726.     return (-1);
  727.     }
  728.   while (isspace (c));
  729.  
  730.   if ((c == '-' || c == '+') && !(l & F_SIGN))
  731.     {
  732.       l |= F_SIGN;
  733.       goto l1;
  734.     }
  735.  
  736.   if (!isdigit (c))
  737.     goto l2;
  738.  
  739. l1:
  740.  
  741.   if (!w)
  742.     goto ret;
  743.  
  744.   if (s)
  745.     *s++ = c;
  746.   n++, w--;
  747.   if ((c = getc (f)) < 0)
  748.     goto ret;
  749.  
  750.   if (isdigit (c))
  751.     goto l1;
  752.  
  753. l2:
  754.  
  755.   if ((c == '-' || c == '+') && (l & F_XP) && !(l & F_XSIGN))
  756.     {
  757.       l |= F_XSIGN;
  758.       goto l1;
  759.     }
  760.   if (c == '.' && !(l & F_DP))
  761.     {
  762.       l |= F_DP;
  763.       goto l1;
  764.     }
  765.   if ((c == 'e' || c == 'E') && !(l & F_XP))
  766.     {
  767.       l |= F_XP;
  768.       goto l1;
  769.     }
  770.  
  771. ret:if (c >= 0)
  772.     (void) ungetc (c, f);
  773.  
  774.   if (!__scflag && n)
  775.     {
  776.       *s = 0;
  777.       i = strtod (__sbuf, 0);
  778.       switch (__scsize)
  779.     {
  780.     case 2:
  781.       *va_arg (*ap, long double *) = (long double) i;
  782.       break;
  783.     case 1:
  784.       *va_arg (*ap, double *) = i;
  785.       break;
  786.     default:
  787.       *va_arg (*ap, float *) = (float) i;
  788.       break;
  789.     }
  790.     }
  791.  
  792.   return (n);
  793.  
  794. #undef F_SIGN
  795. #undef F_DP
  796. #undef F_XP
  797. #undef F_XSIGN
  798. }
  799.  
  800. /* __s_ptr() */
  801.  
  802. static int
  803. __s_ptr (register FILE * f, va_list * ap, const char **e)
  804. {
  805.   return (__s_uhex (f, ap, e));
  806. }
  807.  
  808. /* __s_sdel() */
  809.  
  810. static int
  811. __s_sdel (register FILE * f, va_list * ap, const char **e)
  812. {
  813.   register const char *o;
  814.   register char *s, *d;
  815.   register int w, n = 0, m = 0, c;
  816.  
  817.   if (!(d = __sbuf))
  818.     if (!(d = __sbuf = malloc (SCBUFSIZ)))
  819.       return (0);
  820.  
  821.   o = (*e);
  822.   if (*o == '^')
  823.     o++, m++;
  824.  
  825.   w = SCBUFSIZ;
  826.   if (*o == ']')
  827.     *d++ = *o++, w--;
  828.  
  829.   while (w--)
  830.     {
  831.       if (!(c = *o++) || c == ']')
  832.     break;
  833.       *d++ = c;
  834.     }
  835.  
  836.   (*e) = o;
  837.   *d = 0;
  838.   d = __sbuf;
  839.  
  840.   w = __scwidth;
  841.   if (!w)
  842.     w = SCBUFSIZ;
  843.  
  844.   s = __scflag ? 0 : va_arg (*ap, char *);
  845.  
  846.   if ((c = getc (f)) < 0)
  847.     {
  848.       if (s)
  849.     *s = 0;
  850.       return (-1);
  851.     }
  852.  
  853.   while (w--)
  854.     {
  855.       if (!strchr (d, c) ^ m)
  856.     break;
  857.       if (s)
  858.     *s++ = c;
  859.       n++;
  860.       if ((c = getc (f)) < 0)
  861.     goto ret;
  862.     }
  863.  
  864.   (void) ungetc (c, f);
  865.  
  866. ret:if (s)
  867.     *s = 0;
  868.  
  869.   return (n);
  870. }
  871.